/* Double Linked List */

#ifndef _LINKEDLIST_H
#define _LINKEDLIST_H

typedef struct node_t *ptr_node_t;
typedef struct list_t *ptr_list_t;
typedef struct iterator_t *ptr_iterator_t;

struct node_t
{
  ptr_node_t next;
  ptr_node_t  prev;
  void *data;
};

struct list_t
{
  ptr_node_t header;
  int size;
  // comparison function
  int (*compare)(void *,void *);
  // to string conversion
  int (*to_string)(void *);
};

struct iterator_t
{
  ptr_node_t header;
  ptr_node_t current;
};


/* Node related functions */
extern ptr_node_t llist_make_node(void *d,ptr_node_t n,ptr_node_t p);

/* List related functions */
extern ptr_list_t llist_make_list();
extern ptr_list_t llist_clone_list(ptr_list_t q);
extern void llist_set_comparator(ptr_list_t list,int (*f)(void *,void *));
extern void llist_set_converter(ptr_list_t list,int (*f)(void *));
extern void *llist_add_first(ptr_list_t list,void *d);
extern void *llist_add_last(ptr_list_t list,void *d);
extern void *llist_get_first(ptr_list_t list);
extern void *llist_get_last(ptr_list_t list);
extern void *llist_peek_first(ptr_list_t list);
extern void *llist_peek_last(ptr_list_t list);
extern int llist_get_size(ptr_list_t list);
extern int llist_is_empty(ptr_list_t list);
extern void llist_remove(ptr_list_t list,void *d);
extern void llist_remove_reference(ptr_list_t list,void *d);
extern ptr_iterator_t llist_get_nodes(ptr_list_t list);
extern int llist_contains(ptr_list_t list,void *o);
extern void *llist_search(ptr_list_t list,void *o);
extern void *llist_to_array(ptr_list_t list,size_t size);
extern ptr_list_t llist_get_permutations(ptr_list_t list);
extern char *llist_to_string(ptr_list_t list);
extern int llist_get_rank(ptr_list_t list,void *o);

/* Iterator related functions */
extern ptr_iterator_t llist_iter_make_iterator(ptr_node_t h);
extern int llist_iter_has_next(ptr_iterator_t iter);
extern void *llist_iter_next(ptr_iterator_t iter);

#endif /* _LINKEDLIST_H */
